package ar.edu.itba.pod.legajo47279;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.apache.log4j.Logger;

import ar.edu.itba.node.NodeInformation;
import ar.edu.itba.node.api.ClusterAdministration;

public class ClusterAdministrationRemoteObject implements ClusterAdministration {

	private static final Logger LOGGER = Logger
			.getLogger(ClusterAdministrationRemoteObject.class);

	NodeInformation thisNodeInformation = null;
	Set<NodeInformation> clusterNodes = Collections
			.synchronizedSet(new HashSet<NodeInformation>());

	String groupId = null;

	public ClusterAdministrationRemoteObject(NodeInformation nodeInformation)
			throws RemoteException {
		this.thisNodeInformation = nodeInformation;
		UnicastRemoteObject.exportObject(this, 0);
	}

	@Override
	public void createGroup() throws RemoteException {
		if (groupId != null)
			throw new IllegalStateException(
					"Cluster already binded to a group.");
		else {
			groupId = thisNodeInformation.id();

			LOGGER.info("Succesfully created group at (address,port): ('"
					+ thisNodeInformation.host() + "','"
					+ thisNodeInformation.port() + "').");
		}
	}

	@Override
	public String getGroupId() throws RemoteException {
		return groupId;
	}

	@Override
	public boolean isConnectedToGroup() throws RemoteException {
		return groupId != null;
	}

	@Override
	public void connectToGroup(String host, int port) throws RemoteException,
			NotBoundException {

		// TODO: Preguntar como sabemos con que nombre registraron esto los
		// otros grupos!
		Registry registry = LocateRegistry.getRegistry(host, port);
		ClusterAdministration remoteClusterAdministration = (ClusterAdministration) registry
				.lookup("Constants.CLUSTER_ADMINISTRATION_NAME");

		Set<NodeInformation> clusterNodesInformation = remoteClusterAdministration
				.addNewNode(thisNodeInformation);

		LOGGER.info("Sucessfully connected to the group at " + host);

		for (NodeInformation nodeInformation : clusterNodesInformation) {
			System.out.println("Node at: " + nodeInformation.host() + ", "
					+ nodeInformation.port());
		}
	}

	@Override
	public void disconnectFromGroup(NodeInformation node)
			throws RemoteException, NotBoundException {
		// TODO Auto-generated method stub

	}

	@Override
	public Set<NodeInformation> addNewNode(NodeInformation node)
			throws RemoteException, NotBoundException {
		clusterNodes.add(node);
		return clusterNodes;
	}

	@Override
	public Set<NodeInformation> connectedNodes() throws RemoteException {
		return clusterNodes;
	}

}
